package jpa.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import jpa.model.Entrega;

import org.apache.log4j.Logger;

import jpa.factory.JPADAOFactory;

public class JPAEntregaDAO implements DAO<Entrega> {

	private static Logger logger = Logger.getLogger(JPAEntregaDAO.class);

	private EntityManager manager;

	private EntityTransaction transaction;

	public JPAEntregaDAO() {
		this.manager = this.openPersistence();
	}

	public <T> void closePersistence(T persistence) {
		if (this.manager != null && this.manager.isOpen()) {
			this.manager.close();
		}
	}

	@SuppressWarnings("unchecked")
	public <T> T openPersistence() {
		if (this.manager == null) {
			this.manager = ((EntityManagerFactory) JPADAOFactory.getInstance()
					.getFactory()).createEntityManager();
		}
		return (T) this.manager;
	}

	public <T extends Entrega> void atualizar(T entrega) {
		JPAEntregaDAO.logger.info("Atualizando a entrega: \n" + entrega);

		this.transaction = this.manager.getTransaction();

		if (entrega == null || entrega.getEntrega_id() == null) {
			throw new IllegalStateException("Entrega Inv�lido");
		}
		try {
			this.transaction.begin();
			if (this.manager.contains(entrega)) {
				this.manager.merge(entrega);
			}
			this.manager.flush();
			this.transaction.commit();
		} catch (Exception e) {
			if (this.transaction.isActive())
				this.transaction.rollback();
			throw new IllegalStateException("Problema ao Persistir o Objeto");
		}
	}

	@SuppressWarnings("unchecked")
	public <T extends Entrega> T recuperarPorId(Long id) {
		JPAEntregaDAO.logger.info("Recuperando a entrega por id: " + id);

		if (id == null || id <= 0) {
			throw new IllegalStateException("Identificador Inv�lido");
		}
		return (T) this.manager.find(Entrega.class, id);
	}

	@SuppressWarnings("unchecked")
	public <T extends Entrega> List<T> recuperarTodos() {
		JPAEntregaDAO.logger.info("Recuperando todas as entregas.");

		String consultaJPAQL = "select d from Entrega d";
		Query query = manager.createQuery(consultaJPAQL);
		List<Entrega> categorias = query.getResultList();
		return (List<T>) categorias;
	}

	@SuppressWarnings("unchecked")
	public <T extends Entrega> T remover(Long id) {
		JPAEntregaDAO.logger.info("Removendo a entrega com id: " + id);

		this.transaction = this.manager.getTransaction();
		Entrega entrega = this.recuperarPorId(id);
		if (entrega == null) {
			throw new IllegalStateException("Entrega Inexistente para Remover");
		}
		try {
			this.transaction.begin();
			this.manager.remove(entrega);
			this.manager.flush();
			this.transaction.commit();
			return (T) entrega;
		} catch (Exception e) {
			if (this.transaction.isActive()) {
				this.transaction.rollback();
			}
			throw new IllegalStateException("Problema ao Persistir o Objeto");
		}
	}

	public <T extends Entrega> Long salvar(T entrega) {
		JPAEntregaDAO.logger.info("Salvando a entrega: \n" + entrega);

		this.transaction = this.manager.getTransaction();
		if (entrega == null || entrega.getDataDeEntrega() == null) {
			throw new IllegalStateException("Entrega Inv�lido");
		}
		try {
			this.transaction.begin();
			this.manager.persist(entrega);
			this.manager.flush();
			this.transaction.commit();
			return entrega.getEntrega_id().longValue();
		} catch (Exception e) {
			if (this.transaction.isActive()) {
				this.transaction.rollback();
			}
			e.printStackTrace();
			throw new IllegalStateException("Problema ao Persistir o Objeto");
		}
	}
}
